home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Whiteline: delta
/
whiteline CD Series - delta.iso
/
tools
/
anwender
/
astrolog
/
sources
/
xcharts0.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-25
|
27KB
|
799 lines
/*
** Astrolog (Version 4.40) File: xcharts0.c
**
** IMPORTANT NOTICE: The graphics database and chart display routines
** used in this program are Copyright (C) 1991-1995 by Walter D. Pullen
** (astara@u.washington.edu). Permission is granted to freely use and
** distribute these routines provided one doesn't sell, restrict, or
** profit from them in any way. Modification is allowed provided these
** notices remain with any altered or edited versions of the program.
**
** The main planetary calculation routines used in this program have
** been Copyrighted and the core of this program is basically a
** conversion to C of the routines created by James Neely as listed in
** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
** available from Matrix Software. The copyright gives us permission to
** use the routines for personal use but not to sell them or profit from
** them in any way.
**
** The PostScript code within the core graphics routines are programmed
** and Copyright (C) 1992-1993 by Brian D. Willoughby
** (brianw@sounds.wa.com). Conditions are identical to those above.
**
** The extended accurate ephemeris databases and formulas are from the
** calculation routines in the program "Placalc" and are programmed and
** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
** (alois@azur.ch). The use of that source code is subject to
** regulations made by Astrodienst Zurich, and the code is not in the
** public domain. This copyright notice must not be changed or removed
** by any user of this program.
**
** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
** X Window graphics initially programmed 10/23-29/1991.
** PostScript graphics initially programmed 11/29-30/1992.
** Last code change made 1/29/1995.
*/
#include "astrolog.h"
#ifdef GRAPH
/*
******************************************************************************
** Subchart Graphics Routines.
******************************************************************************
*/
/* Given a string, draw it on the screen using the given color. The */
/* position of the text is based the saved positions of where we drew the */
/* text the last time the routine was called, being either directly below */
/* in the same column or in the same row just to the right. This is used */
/* by the sidebar drawing routine to print a list of text on the chart. */
int DrawPrint(sz, m, n)
char *sz;
int m, n;
{
static int x0, x, y;
if (sz == NULL) { /* Null string means just initialize position. */
x0 = x = m; y = n;
return y;
}
if (y >= gs.yWin-1) /* Don't draw if we've scrolled off the chart bottom. */
return y;
DrawColor(m);
DrawSz(sz, x, y, dtLeft | dtBottom);
/* If the second parameter is TRUE, we stay on the same line, otherwise */
/* when FALSE we go to the next line at the original column setting. */
if (n)
x += CchSz(sz)*xFont*gi.nScaleT;
else {
x = x0;
n = y;
y += yFont*gi.nScaleT;
}
return y;
}
/* Print text showing the chart information and house and planet positions */
/* of a chart in a "sidebar" to the right of the chart in question. This */
/* is always done for the -v and -w graphic wheel charts unless the -v0 */
/* switch flag is also set, in which case none of the stuff here is done. */
void DrawInfo()
{
char sz[cchSzDef];
ET et;
int i, y, a, s;
#ifdef INTERPRET
int tot, abo, lef;
/* Hack: Just for fun, if interpretation is active (which normally has */
/* no effect whatsoever on graphics) we'll decorate the chart a little. */
if (us.fInterpret) {
if (us.nScreenWidth & 1) {
/* If screenwidth value is odd, draw a moire pattern in each corner. */
abo = gs.yWin/(us.nScreenWidth/10);
lef = gs.xWin/(us.nScreenWidth/10);
for (y = 0; y <= 1; y++)
for (i = 0; i <= 1; i++)
for (s = 0; s <= 1; s++)
for (a = 1; a < (s ? lef : abo)*2; a++) {
DrawColor(a & 1 ? gi.kiGray : gi.kiOff);
DrawLine(i ? gs.xWin-1-lef : lef, y ? gs.yWin-1-abo : abo,
s ? (i ? gs.xWin-1-a : a) : i*(gs.xWin-1),
s ? y*(gs.yWin-1) : (y ? gs.yWin-1-a : a));
}
} else {
/* If screenwidth is even, draw spider web lines in each corner. */
DrawColor(gi.kiGray);
tot = us.nScreenWidth*3/20;
abo = gs.yWin/4;
lef = gs.xWin/4;
for (y = 0; y <= 1; y++)
for (i = 0; i <= 1; i++)
for (a = 1; a < tot; a++)
DrawLine(i*(gs.xWin-1), y ? (gs.yWin-1-a*abo/tot) : a*abo/tot,
i ? gs.xWin-1-lef+a*lef/tot : lef-a*lef/tot, y*(gs.yWin-1));
}
}
#endif
if (!gs.fText || us.fVelocity) /* Don't draw sidebar if */
return; /* -v0 flag is set. */
a = us.fAnsi;
us.fAnsi = -(!gs.fFont || (!gs.fMeta && !gs.fPS));
DrawColor(gi.kiLite);
if (gs.fBorder)
DrawLine(gs.xWin-1, 0, gs.xWin-1, gs.yWin-1);
gs.xWin += xSideT;
DrawPrint(NULL, gs.xWin-xSideT+xFontT-gi.nScaleT, yFont*7/5*gi.nScaleT);
/* Print chart header and setting information. */
sprintf(sz, "%s %s", szAppName, szVersionCore);
DrawPrint(sz, gi.kiOn, fFalse);
if (*ciMain.nam)
DrawPrint(ciMain.nam, gi.kiLite, fFalse);
if (Mon == -1)
sprintf(sz, "No time or space.");
else if (us.nRel == rcComposite)
sprintf(sz, "Composite chart.");
else {
sprintf(sz, "%c%c%c %s", chDay3(DayOfWeek(Mon, Day, Yea)),
SzDate(Mon, Day, Yea, fTrue));
DrawPrint(sz, gi.kiLite, fFalse);
DrawPrint(SzTim(Tim), gi.kiLite, fTrue);
sprintf(sz, " (%cT %s GMT)", Dst != 0.0 ? 'D' : 'S', SzZone(Zon));
}
DrawPrint(sz, gi.kiLite, fFalse);
if (*ciMain.loc)
DrawPrint(ciMain.loc, gi.kiLite, fFalse);
DrawPrint(SzLocation(Lon, Lat), gi.kiLite, fFalse);
sprintf(sz, "%s houses.", szSystem[us.nHouseSystem]);
DrawPrint(sz, gi.kiLite, fFalse);
sprintf(sz, "%s, %s.", us.fSiderial ? "Sidereal" : "Tropical",
us.objCenter == 0 ? "Heliocentric" :
(us.objCenter == 1 ? "Geocentric" : szObjName[us.objCenter]));
DrawPrint(sz, gi.kiLite, fFalse);
sprintf(sz, "Julian Day = %11.4f", JulianDayFromTime(T));
DrawPrint(sz, gi.kiLite, fFalse);
/* Print house cusp positions. */
DrawPrint("", gi.kiLite, fFalse);
for (i = 1; i <= cSign; i++) {
sprintf(sz, "%2d%s house: ", i, szSuffix[i]);
y = DrawPrint(sz, kSignB(i), fTrue);
if (!is.fSeconds && (gs.nScale == 100 ||
!gs.fFont || !gi.fFile || gs.fBitmap) && y < gs.yWin-1) {
s = gi.nScale;
gi.nScale = gi.nScaleT;
DrawSign(SFromZ(house[i]), gs.xWin-12*gi.nScaleT,
y-(yFont/2-1)*gi.nScaleT);
gi.nScale = s;
}
DrawPrint(SzZodiac(house[i]), kSignB(SFromZ(house[i])), fFalse);
}
/* Print planet positions. */
DrawPrint("", gi.kiLite, fFalse);
for (i = 1; i <= oNorm; i++) if (!ignore[i] && !FCusp(i)) {
sprintf(sz, is.fSeconds ? "%3.3s: " : "%4.4s: ", szObjName[i]);
DrawPrint(sz, kObjB[i], fTrue);
y = DrawPrint(SzZodiac(planet[i]), kSignB(SFromZ(planet[i])), fTrue);
if (!is.fSeconds && i < starLo && (gs.nScale == 100 ||
!gs.fFont || !gi.fFile || gs.fBitmap) && y < gs.yWin-1) {
s = gi.nScale;
gi.nScale = gi.nScaleT;
DrawObject(i, gs.xWin-12*gi.nScaleT, y-(yFont/2-1)*gi.nScaleT);
gi.nScale = s;
}
sprintf(sz, "%c ", ret[i] < 0.0 ? chRet : ' ');
s = FThing(i);
DrawPrint(sz, gi.kiOn, s);
if (s) {
is.fSeconds = fFalse;
DrawPrint(SzAltitude(planetalt[i]), gi.kiLite, fFalse);
is.fSeconds = us.fSeconds;
}
}
/* Print star positions. */
for (i = starLo; i <= starHi; i++) if (!ignore[i]) {
s = oNorm+starname[i-oNorm];
sprintf(sz, is.fSeconds ? "%3.3s: " : "%4.4s: ", szObjName[s]);
DrawPrint(sz, kObjB[s], fTrue);
DrawPrint(SzZodiac(planet[s]), kSignB(SFromZ(planet[s])), fTrue);
DrawPrint(" ", gi.kiOn, fTrue);
DrawPrint(SzAltitude(planetalt[s]), gi.kiLite, fFalse);
}
/* Print element table information. */
DrawPrint("", gi.kiLite, fFalse);
CreateElemTable(&et);
sprintf(sz, "Fire: %d, Earth: %d,", et.coElem[eFir], et.coElem[eEar]);
DrawPrint(sz, gi.kiLite, fFalse);
sprintf(sz, "Air : %d, Water: %d", et.coElem[eAir], et.coElem[eWat]);
DrawPrint(sz, gi.kiLite, fFalse);
sprintf(sz, "Car: %d, Fix: %d, Mut: %d",
et.coMode[0], et.coMode[1], et.coMode[2]);
DrawPrint(sz, gi.kiLite, fFalse);
sprintf(sz, "Yang: %d, Yin: %d", et.coYang, et.coYin);
DrawPrint(sz, gi.kiLite, fFalse);
sprintf(sz, "M: %d, N: %d, A: %d, D: %d",
et.coMC, et.coIC, et.coAsc, et.coDes);
DrawPrint(sz, gi.kiLite, fFalse);
sprintf(sz, "Ang: %d, Suc: %d, Cad: %d",
et.coModeH[0], et.coModeH[1], et.coModeH[2]);
DrawPrint(sz, gi.kiLite, fFalse);
sprintf(sz, "Learn: %d, Share: %d", et.coLearn, et.coShare);
DrawPrint(sz, gi.kiLite, fFalse);
us.fAnsi = a;
}
/*
******************************************************************************
** Map Chart Routines.
******************************************************************************
*/
/* Another stream reader, this one is used by the globe drawing routine: */
/* for the next body of land/water, return its name (and color), its */
/* longitude and latitude, and a vector description of its outline. */
bool FReadWorldData(nam, loc, lin)
char FAR **nam, FAR **loc, FAR **lin;
{
static char FAR **psz = (char FAR **)szWorldData;
int i;
*loc = *psz++;
*lin = *psz++;
*nam = *psz++;
if (*loc[0]) {
if (gs.fPrintMap && gi.fFile) {
i = **nam - '0';
AnsiColor(i ? kRainbowA[i] : kMainA[7]);
PrintSz(*nam+1); PrintL();
}
return fTrue;
}
psz = (char FAR **)szWorldData; /* Reset stream when no data left. */
return fFalse;
}
/* Given longitude and latitude values on a globe, return the window */
/* coordinates corresponding to them. In other words, project the globe */
/* onto the view plane, and return where our coordinates got projected to, */
/* as well as whether our location is hidden on the back side of the globe. */
bool FGlobeCalc(x1, y1, u, v, cx, cy, rx, ry, deg)
real x1, y1;
int *u, *v, cx, cy, rx, ry, deg;
{
real j, siny1;
/* Compute coordinates for a general globe invoked with -XG switch. */
if (gi.nMode == gGlobe) {
x1 = Mod(x1+(real)deg); /* Shift by current globe rotation value. */
if (gs.rTilt != 0.0) {
/* Do another coordinate shift if the globe's equator is tilted any. */
x1 = RFromD(x1); y1 = RFromD(rDegQuad-y1);
CoorXform(&x1, &y1, RFromD(gs.rTilt));
x1 = Mod(DFromR(x1)); y1 = rDegQuad-DFromR(y1);
}
*v = cy + (int)((real)ry*-RCosD(y1)-rRound);
*u = cx + (int)((real)rx*-RCosD(x1)*RSinD(y1)-rRound);
return x1 > rDegHalf;
}
/* Compute coordinates for a polar globe invoked with -XP switch. */
siny1 = RSinD(y1);
j = gs.fAlt ? rDegQuad+x1+deg : 270.0-x1-deg;
*v = cy + (int)(siny1*(real)ry*RSinD(j)-rRound);
*u = cx + (int)(siny1*(real)rx*RCosD(j)-rRound);
return gs.fAlt ? y1 < rDegQuad : y1 > rDegQuad;
}
/* Draw one "Ley line" on the world map, based coordinates given in terms of */
/* longitude and vertical fractional distance from the center of the earth. */
void DrawLeyLine(l1, f1, l2, f2)
real l1, f1, l2, f2;
{
l1 = Mod(l1); l2 = Mod(l2);
/* Convert vertical fractional distance to a corresponding coordinate. */
f1 = rDegQuad-RAsin(f1)/rPiHalf*rDegQuad;
f2 = rDegQuad-RAsin(f2)/rPiHalf*rDegQuad;
DrawWrap((int)(l1*(real)gi.nScale+rRound)+1,
(int)(f1*(real)gi.nScale+rRound)+1,
(int)(l2*(real)gi.nScale+rRound)+1,
(int)(f2*(real)gi.nScale+rRound)+1, 1, gs.xWin-2);
}
/* Draw the main set of planetary Ley lines on the map of the world. This */
/* consists of drawing an icosahedron and then a dodecahedron lattice. */
void DrawLeyLines(deg)
int deg;
{
real off = (real)deg, phi, h, h1, h2, r, i;
phi = (RSqr(5.0)+1.0)/2.0; /* Icosahedron constants. */
h = 1.0/(phi*2.0-1.0);
DrawColor(kMainB[6]);
for (i = off; i < rDegMax+off; i += 72.0) { /* Draw icosahedron edges. */
DrawLeyLine(i, h, i+72.0, h);
DrawLeyLine(i-36.0, -h, i+36.0, -h);
DrawLeyLine(i, h, i, 1.0);
DrawLeyLine(i+36.0, -h, i+36.0, -1.0);
DrawLeyLine(i, h, i+36.0, -h);
DrawLeyLine(i, h, i-36.0, -h);
}
r = 1.0/RSqr(3.0)/phi/RCos(RFromD(54.0)); /* Dodecahedron constants. */
h2 = RSqr(1.0-r*r); h1 = h2/(phi*2.0+1.0);
DrawColor(kMainB[4]);
for (i = off; i < rDegMax+off; i += 72.0) { /* Draw docecahedron edges. */
DrawLeyLine(i-36.0, h2, i+36.0, h2);
DrawLeyLine(i, -h2, i+72.0, -h2);
DrawLeyLine(i+36.0, h2, i+36.0, h1);
DrawLeyLine(i, -h2, i, -h1);
DrawLeyLine(i+36.0, h1, i+72.0, -h1);
DrawLeyLine(i+36.0, h1, i, -h1);
}
}
/* This major routine draws all of Astrolog's map charts. This means */
/* either the world map or the constellations, in either rectangular or */
/* globe hemisphere form. The rectangular chart may also be done in a */
/* Mollewide projection, for six total combinations. We shift the chart by */
/* specified rotational and tilt values, and may draw on the chart each */
/* planet at its zenith position on Earth or location in constellations. */
void DrawMap(fSky, fGlobe, deg)
bool fSky, fGlobe;
int deg;
{
char *nam, *loc, *lin, chCmd;
int X[objMax], Y[objMax], M[objMax], N[objMax],
cx = gs.xWin/2, cy = gs.yWin/2, rx, ry, lon, lat, unit = 12*gi.nScale,
x, y, xold, yold, m, n, u, v, i, j, k, l, nScl = gi.nScale;
bool fNext = fTrue, fCan;
real planet1[objMax], planet2[objMax], x1, y1, rT;
#ifdef CONSTEL
char *pch;
bool fBlank;
int isz = 0, nC, xT, yT, xDelta, yDelta, xLo, xHi, yLo, yHi;
#endif
/* Set up some variables. */
rx = cx-1; ry = cy-1;
if (fGlobe)
fCan = (gs.rTilt == 0.0 && gi.nMode != gPolar);
#ifdef CONSTEL
/* Draw a dot grid for large rectangular constellation charts. */
if (fSky && !fGlobe && !gs.fMollewide && gi.nScale/gi.nScaleT > 2)
for (yT = 5; yT < nDegHalf; yT += 5)
for (xT = 5; xT <= nDegMax; xT += 5) {
DrawColor(xT % 15 == 0 && yT % 10 == 0 ? gi.kiOn : gi.kiGray);
x = xT+deg;
if (x > nDegMax)
x -= nDegMax;
DrawPoint(x*nScl, yT*nScl);
}
#endif
loop {
/* Get the next chunk of data to process. Get the starting position, */
/* map it to the screen, and set the drawing color appropriately. */
if (fNext) {
fNext = fFalse;
/* For constellations, get data for the next constellation shape. */
if (fSky) {
#ifdef CONSTEL
isz++;
if (isz > cCnstl)
break;
DrawColor(gs.fAlt && gi.nMode != gPolar && (gi.nMode != gWorldMap ||
!gs.fMollewide) ? kMainB[7] : kRainbowB[6]);
pch = (char *)szDrawConstel[isz];
lon = nDegMax -
(((pch[2]-'0')*10+(pch[3]-'0'))*15+(pch[4]-'0')*10+(pch[5]-'0'));
lat = 90-((pch[6] == '-' ? -1 : 1)*((pch[7]-'0')*10+(pch[8]-'0')));
pch += 9;
xLo = xHi = xT = xold = x = lon;
yLo = yHi = yT = yold = y = lat;
nC = 0;
if (fGlobe) {
FGlobeCalc((real)x, (real)y, &m, &n, cx, cy, rx, ry, deg);
k = l = fTrue;
} else {
xold += deg;
x += deg;
}
#else
;
#endif
/* For world maps, get data for the next coastline piece. */
} else {
if (!FReadWorldData(&nam, &loc, &lin))
break;
i = nam[0]-'0';
DrawColor((!fGlobe && gi.nMode == gAstroGraph) ? gi.kiOn :
(gi.nMode == gGlobe && gs.fAlt) ? gi.kiGray :
(i ? kRainbowB[i] : kMainB[7]));
lon = (loc[0] == '+' ? 1 : -1)*
((loc[1]-'0')*100 + (loc[2]-'0')*10 + (loc[3]-'0'));
lat = (loc[4] == '+' ? 1 : -1)*((loc[5]-'0')*10 + (loc[6]-'0'));
if (fGlobe) {
x = 180-lon;
y = 90-lat;
FGlobeCalc((real)x, (real)y, &m, &n, cx, cy, rx, ry, deg);
k = l = fTrue;
} else {
xold = x = 181-lon+deg;
yold = y = 91-lat;
}
}
}
/* Get the next unit from the string to draw on the screen as a line. */
if (fSky) {
/* For constellations we have a cache of how long we should keep */
/* going in the previous direction, as say "u5" for up five should */
/* move our pointer up five times without advancing string pointer. */
#ifdef CONSTEL
if (nC <= 0) {
if (!(chCmd = *pch)) {
fNext = fTrue;
if (gs.fText) {
/* If we've reached the end of current constellation, compute */
/* the center location in it based on lower and upper bounds */
/* we've maintained, and print the name of the constel there. */
xT = xLo + (xHi - xLo)*(szDrawConstel[isz][0]-'1')/8;
yT = yLo + (yHi - yLo)*(szDrawConstel[isz][1]-'1')/8;
if (xT < 0)
xT += nDegMax;
else if (xT > nDegMax)
xT -= nDegMax;
if (fGlobe) {
if (FGlobeCalc((real)xT, (real)yT, &x, &y, cx, cy, rx, ry, deg))
continue;
} else {
xT += deg;
if (xT > nDegMax)
xT -= nDegMax;
if (gs.fMollewide)
x = 180*nScl + NMultDiv(xT-180, NMollewide(yT-91), 180L);
else
x = xT*nScl;
y = yT*nScl;
}
DrawColor(gs.fAlt && gi.nMode != gPolar && (gi.nMode !=
gWorldMap || !gs.fMollewide) ? gi.kiGray : kMainB[5]);
DrawSz(szCnstlAbbrev[isz], x, y, dtCent);
}
continue;
}
pch++;
/* Get the next direction and distance from constellation string. */
if (fBlank = (chCmd == 'b'))
chCmd = *pch++;
xDelta = yDelta = 0;
switch (chCmd) {
case 'u': yDelta = -1; break; /* Up */
case 'd': yDelta = 1; break; /* Down */
case 'l': xDelta = -1; break; /* Left */
case 'r': xDelta = 1; break; /* Right */
case 'U': yDelta = -1; nC = (yT-1)%10+1; break; /* Up until */
case 'D': yDelta = 1; nC = 10-yT%10; break; /* Down until */
case 'L': xDelta = -1; nC = (xT+599)%15+1; break; /* Left until */
case 'R': xDelta = 1; nC = 15-(xT+600)%15; break; /* Right until */
default: PrintError("Bad draw."); /* Shouldn't happen. */
}
if (chCmd >= 'a')
nC = NFromPch(&pch); /* Figure out how far to draw. */
}
nC--;
xT += xDelta; x += xDelta;
yT += yDelta; y += yDelta;
if (fBlank) {
xold = x; yold = y; /* We occasionally want to move the pointer */
l = fFalse; /* without drawing the line on the screen. */
continue;
}
if (xT < xLo) /* Maintain our bounding rectangle for this */
xLo = xT; /* constellation if we crossed over it any. */
else if (xT > xHi)
xHi = xT;
if (yT < yLo)
yLo = yT;
else if (yT > yHi)
yHi = yT;
#else
;
#endif
} else {
/* Get the next unit from the much simpler world map strings. */
if (!(chCmd = *lin)) {
fNext = fTrue;
continue;
}
lin++;
/* Each unit is exactly one character in the coastline string. */
if (chCmd == 'L' || chCmd == 'H' || chCmd == 'G')
x--;
else if (chCmd == 'R' || chCmd == 'E' || chCmd == 'F')
x++;
if (chCmd == 'U' || chCmd == 'H' || chCmd == 'E')
y--;
else if (chCmd == 'D' || chCmd == 'G' || chCmd == 'F')
y++;
}
/* Transform map coordinates to screen coordinates and draw a line. */
while (x >= nDegMax) /* Take care of coordinate wrap around. */
x -= nDegMax;
while (x < 0)
x += nDegMax;
if (abs(x-xold) > nDegHalf)
xold = x;
if (fGlobe) {
/* For globes, we have to go do a complicated transformation, and not */
/* draw when we're hidden on the back side of the sphere. We're smart */
/* and try to only do the slow stuff when we know we'll be visible. */
if (fCan) {
k = x+deg;
if (k >= nDegMax)
k -= nDegMax;
k = (k <= 180);
}
if (k && !FGlobeCalc((real)x, (real)y, &u, &v, cx, cy, rx, ry, deg)) {
if (l)
DrawLine(m, n, u, v);
m = u; n = v;
l = fTrue;
} else
l = fFalse;
} else {
/* Rectangular maps are much simpler, with screen coordinates */
/* proportional to internal coords. For the Mollewide projection */
/* we have to apply a factor to the horizontal positioning though. */
if (gs.fMollewide && gi.nMode != gAstroGraph)
DrawLine(180*nScl + NMultDiv(xold-180,
NMollewide(yold-91), 180L), yold*nScl,
180*nScl + NMultDiv(x-180, NMollewide(y-91), 180L), y*nScl);
else
DrawLine(xold*nScl, yold*nScl, x*nScl, y*nScl);
xold = x; yold = y;
}
}
/* Draw the outline of the map, either a circle around globes or a */
/* Mollewide type ellipse for that type of rectangular chart. */
DrawColor(gi.kiOn);
if (!fGlobe) {
if (gs.fMollewide && gi.nMode != gAstroGraph)
if (!gs.fAlt)
for (xold = 0, y = -89; y <= 90; y++, xold = x)
for (x = NMollewide(y), i = -1; i <= 1; i += 2)
{
DrawLine(180*nScl + i*xold - (i == 1), (90+y)*nScl,
180*nScl + i*x - (i == 1), (91+y)*nScl);
}
} else
DrawEllipse(0, 0, gs.xWin-1, gs.yWin-1);
/* Now, if we are in an appropriate bonus chart mode, draw each planet at */
/* its zenith or visible location on the globe or map, if not hidden. */
if (!gs.fAlt || (gi.nMode != gGlobe &&
(!fSky || gi.nMode != gWorldMap || gs.fMollewide)))
return;
rT = gs.fConstel ? rDegHalf - (fGlobe ? 0.0 : (real)deg) : Lon;
if (rT < 0.0)
rT += rDegMax;
for (i = 1; i <= cObj; i++) {
planet1[i] = RFromD(Tropical(planet[i]));
planet2[i] = RFromD(planetalt[i]);
EclToEqu(&planet1[i], &planet2[i]); /* Calculate zenith long. & lat. */
}
/* Compute screen coordinates of each object, if it's even visible. */
for (i = 1; i <= cObj; i++) if (FProper(i)) {
if (fSky)
x1 = planet1[i];
else
x1 = planet1[oMC]-planet1[i];
if (x1 < 0.0)
x1 += 2.0*rPi;
if (x1 > rPi)
x1 -= 2.0*rPi;
x1 = Mod(rDegHalf-rT-DFromR(x1));
y1 = rDegQuad-DFromR(planet2[i]);
if (fGlobe) {
X[i] = FGlobeCalc(x1, y1, &u, &v, cx, cy, rx, ry, deg) ? -1000 : u;
Y[i] = v;
} else {
X[i] = (int)(x1 * (real)nScl);
Y[i] = (int)(y1 * (real)nScl);
}
M[i] = X[i]; N[i] = Y[i]+unit/2;
}
/* Now that we have the coordinates of each object, figure out where to */
/* draw the glyphs. Again we try not to draw glyphs on top of each other. */
for (i = 1; i <= cObj; i++) if (FProper(i)) {
k = l = gs.xWin+gs.yWin;
/* For each planet, we draw the glyph either right over or right under */
/* the actual zenith location point. So, find out the closest distance */
/* of any other planet assuming we place ours at both possibilities. */
for (j = 1; j < i; j++) if (FProper(j)) {
k = Min(k, abs(M[i]-M[j])+abs(N[i]-N[j]));
l = Min(l, abs(M[i]-M[j])+abs(N[i]-unit-N[j]));
}
/* Normally, we put the glyph right below the actual point. If however */
/* another planet is close enough to have their glyphs overlap, and the */
/* above location is better, then we'll draw the glyph above instead. */
if (k < unit || l < unit)
if (k < l)
N[i] -= unit;
}
for (i = cObj; i >= 1; i--) if (X[i] >= 0 && FProper(i)) /* Draw the */
DrawObject(i, M[i], N[i]); /* glyphs. */
for (i = cObj; i >= 1; i--) if (X[i] >= 0 && FProper(i)) {
DrawColor(kObjB[i]);
DrawSpot(X[i], Y[i]);
}
}
/* Create a chart in the window based on the current graphics chart mode. */
/* This is the main dispatch routine for all of the program's graphics. */
void DrawChartX()
{
char sz[cchSzDef];
int i;
bool fT;
gi.nScale = gs.nScale/100;
if (gs.fBitmap || gs.fMeta)
PrintNotice("Creating graphics chart in memory.");
DrawClearScreen();
#ifdef CONSTEL
fT = gs.fConstel;
#else
fT = fFalse;
#endif
switch (gi.nMode) {
case gWheel:
case gHouse:
if (us.nRel > rcDual)
XChartWheel();
else
XChartWheelRelation();
break;
case gGrid:
if (us.nRel > rcDual)
XChartGrid();
else
XChartGridRelation();
break;
case gHorizon:
if (us.fPrimeVert)
XChartHorizonSky();
else
XChartHorizon();
break;
case gOrbit:
XChartOrbit();
break;
case gDisposit:
XChartDispositor();
break;
case gAstroGraph:
DrawMap(fFalse, fFalse, gs.nRot); /* First draw map of world. */
XChartAstroGraph(); /* Then draw astro-graph lines on it. */
break;
case gCalendar:
XChartCalendar();
break;
case gEphemeris:
XChartEphemeris();
break;
case gWorldMap:
DrawMap(fT, fFalse, gs.nRot); /* First draw map of world. */
if (!fT && gs.fAlt && !gs.fMollewide) /* Then maybe Ley lines. */
DrawLeyLines(gs.nRot);
break;
case gGlobe:
case gPolar:
DrawMap(fT, fTrue, gs.nRot);
break;
#ifdef BIORHYTHM
case gBiorhythm:
XChartBiorhythm();
break;
#endif
}
/* Print text showing chart information at bottom of window. */
DrawColor(gi.kiLite);
if (fDrawText) {
if (Mon == -1)
sprintf(sz, "(No time or space)");
else if (us.nRel == rcComposite)
sprintf(sz, "(Composite)");
else {
fT = us.fAnsi; us.fAnsi = -(!gs.fFont || (!gs.fMeta && !gs.fPS));
i = DayOfWeek(Mon, Day, Yea);
sprintf(sz, "%c%c%c %s %s (%cT %s GMT) %s", chDay3(i),
SzDate(Mon, Day, Yea, 2), SzTim(Tim), Dst != 0.0 ? 'D' : 'S',
SzZone(Zon), SzLocation(Lon, Lat));
us.fAnsi = fT;
}
DrawSz(sz, gs.xWin/2, gs.yWin-3*gi.nScaleT, dtBottom | dtErase);
}
/* Draw a border around the chart if the mode is set and appropriate. */
if (fDrawBorder)
DrawEdgeAll();
}
#endif /* GRAPH */
/* xcharts0.c */